package com.maya.medicalwastes.httpNet;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.NonNull;

import com.maya.medicalwastes.HttpCodeConstant;
import com.maya.medicalwastes.ReceiverActionConstant;
import com.maya.medicalwastes.httpNet.callback.FileResponseCallBack;
import com.maya.medicalwastes.httpNet.callback.ResponseCallBack;
import com.maya.medicalwastes.httpNet.model.ResultBaseModel;
import com.maya.medicalwastes.httpNet.util.SharePreferenceOperation;
import com.maya.medicalwastes.util.FileUtils;
import com.maya.medicalwastes.util.MyUtils;
import com.maya.medicalwastes.util.ToastUtils;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import okhttp3.ResponseBody;
import retrofit2.HttpException;


/**
 * @description 创建线程访问网络
 * @user gzl
 * @date 2017/5/31
 * @time 15:53
 */
public class HttpService<T> {
    public static HttpService instance;

    public static HttpService getInstance() {
        if (instance == null) {
            synchronized (HttpService.class) {
                instance = new HttpService();
            }
        }
        return instance;
    }
    //Schedulers.io() 代表io操作的线程, 通常用于网络,读写文件等io密集型的操作
    //
    //Schedulers.computation() 代表CPU计算密集型的操作, 例如需要大量计算的操作
    //
    //Schedulers.newThread() 代表一个常规的新线程
    //
    //AndroidSchedulers.mainThread() 代表Android的主线程

    /**
     * @description 常用网络接口数据访问
     * @author gzl
     * @time 2017/6/2 9:00
     */
    public void enqueue(Observable<T> observable, final ResponseCallBack<T> callBack, final Context context) {
        observable.subscribeOn(Schedulers.io())//在工作线程请求网络  指定Observable自身在哪个调度器上执行也是叫做上游 以第一次的指定为准
                .observeOn(AndroidSchedulers.mainThread())//在主线程处理结果
                //.observeOn(Schedulers.newThread())//在主线程处理结果 指定一个观察者在哪个调度器上观察这个Observable也是叫做下游 以最后一次指定为准
                .subscribe(new Observer<T>() {

                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull T response) {
                        if (!(response instanceof ResponseBody)) {
                            System.out.print(response);
                            String errorString = "";
                            switch (((ResultBaseModel) response).httpCode) {
                                case HttpCodeConstant.NO_LOGIN:
                                    if (context != null) {
                                     /*   ToastUtils.ViewToast(context, "未登录");
                                        SharePreferenceOperation.clearUserAllInformation(context);
                                        //未登录发送广播转跳到登录界面
                                        context.sendBroadcast(new Intent(ReceiverActionConstant.AUTH_FAILED));*/

                                        //调用login接口
                                        autoLogin(context);
                                    }
                                    break;
                                case HttpCodeConstant.SUCCESS:
                                    callBack.onResponse(response);
                                    break;
                                case HttpCodeConstant.SERVER_ERROR:
                                    ToastUtils.ViewToast(context, "服务器错误");
                                    callBack.onFailure(((ResultBaseModel) response).httpCode);
                                    break;
                                case HttpCodeConstant.USERNAME_ERROR:
                                    ToastUtils.ViewToast(context, ((ResultBaseModel) response).msg);
                                    callBack.onFailure(((ResultBaseModel) response).httpCode);
                                    break;
                                default:
                                    try {
                                        ToastUtils.ViewToast(context, ((ResultBaseModel) response).msg);
                                        callBack.onFailure(((ResultBaseModel) response).httpCode);
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                    break;
                            }
                        } else {
                            callBack.onResponse(response);
                        }
                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        if (e instanceof HttpException) {
                            if (((HttpException) e).code() == 401) {
                                //未登录
                                ToastUtils.ViewToast(context, "未登录");
                                SharePreferenceOperation.clearUserAllInformation(context);
                                //未登录发送广播转跳到登录界面
                                context.sendBroadcast(new Intent(ReceiverActionConstant.AUTH_FAILED));
                            } else {
                                ToastUtils.ViewToast(context, e.getMessage());
                                callBack.onFailure(HttpCodeConstant.CANNOT_COMBINE_SERVE);
                            }
                        } else {
                            ToastUtils.ViewToast(context, e.getMessage());
                            callBack.onFailure(HttpCodeConstant.CANNOT_COMBINE_SERVE);
                        }

                    }

                    @Override
                    public void onComplete() {
                    }
                });
    }

    private void autoLogin(Context context) {
        //showDialog();
       /* ToastUtils.ViewToast(context, "token已失效，正在重新登陆");
        HashMap<String, String> params;
        params = new HashMap<>();
        params.put("account", PrefUtils.getString(context, SharedPreferencesConstant.USER_NAME, ""));
        params.put("password", PrefUtils.getString(context, SharedPreferencesConstant.PASSWORD, ""));
        params.put("authOrgId", PrefUtils.getString(context, "authOrgId", ""));
        Observable<ResultModel<String>> call = RetrofitManager.getInstance().getRetrofit().create(BaseService.class).loginCall(params);
        HttpService.getInstance().enqueue(call, new ResponseCallBack<ResultModel<String>>() {
            @Override
            public void onResponse(ResultModel<String> response) {
                if (response != null && response.httpCode == 200) {
                    if (!StringUtils.isEmpty(response.data)) {
                        PrefUtils.putString(context, SharedPreferencesConstant.TOKEN, response.data);
                    } else {
                        ToastUtils.ViewToast(context, "登录失败");
                    }
                }
                sendCloseDialogBroadCast(context);
            }

            @Override
            public void onFailure(int httpCode) {
                //closeDialog();
            }
        }, context);*/

        ToastUtils.ViewToast(context, "token已失效，正在重新登陆");
        Bundle bundle = new Bundle();
        bundle.putBoolean("isAutoLogin", true);
        // MyUtils.IntentToNew(context, X5WebViewHelper.getLoginClassName(context), bundle);
        // AppManager.finishAllActivity();
    }

/*    private void sendCloseDialogBroadCast(Context context) {
        LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(context);
        Intent intent = new Intent(ReceiverActionConstant.CLOSE_DIALOG);
        localBroadcastManager.sendBroadcast(intent);
    }*/

    /**
     * @description 下载文件接口数据访问
     * @author gzl
     * @time 2017/6/2 9:00
     */

    public void downloadFile(final String name, Observable<ResponseBody> observable, final FileResponseCallBack callBack, final Context context) {
        observable.subscribeOn(Schedulers.io())//在工作线程请求网络
                .observeOn(Schedulers.io())//在主线程处理结果
                .subscribe(new Observer<ResponseBody>() {

                    @Override
                    public void onSubscribe(@NonNull Disposable d) {

                    }

                    @Override
                    public void onNext(@NonNull ResponseBody response) {
                        try {
                            if (FileUtils.fileExists(name)) {
                                new File(name).delete();
                            }
                            InputStream is = response.byteStream();
                            File file = new File(name);
                            FileOutputStream fos = new FileOutputStream(file);
                            BufferedInputStream bis = new BufferedInputStream(is);
                            long total = response.contentLength();
                            callBack.onProgress(0);
                            byte[] buffer = new byte[1024];
                            int len;
                            int process = 0;
                            while ((len = bis.read(buffer)) != -1) {
                                process += len;
                                callBack.onProgress((int) (((float) process / total) * 100));
//                                callBack.onProgress(((float) process / total) * 100);
                                fos.write(buffer, 0, len);
                                fos.flush();
                            }
                            fos.close();
                            bis.close();
                            is.close();
                            callBack.onDownloadComplete();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    }

                    @Override
                    public void onError(@NonNull Throwable e) {
                        callBack.onFailure(e);
                    }

                    @Override
                    public void onComplete() {
                    }
                });
    }
}
